const input = document.querySelectorAll('textarea')[0],
  characterCount = document.querySelector('#characterCount'),
  wordCount = document.querySelector('#wordCount'),
  sentenceCount = document.querySelector('#sentenceCount'),
  paragraphCount = document.querySelector('#paragraphCount'),
  readingTime = document.querySelector('#readingTime'),
  readability = document.querySelector('#readability'),
  keywordsDiv = document.querySelectorAll('.keywords')[0],
  topKeywords = document.querySelector('#topKeywords');

// updating the displayed stats after every keypress
input.addEventListener('keyup', function () {
  // character count
  // just displaying the input length as everything is a character
  characterCount.innerHTML = input.value.length;

  // word count using \w metacharacter - replacing this with .* to match anything between word boundaries since it was not taking 'a' as a word.
  // this is a masterstroke - to count words with any number of hyphens as one word
  // [-?(\w+)?]+ looks for hyphen and a word (we make both optional with ?). + at the end makes it a repeated pattern
  // \b is word boundary metacharacter
  const words = input.value.match(/\b[-?(\w+)?]+\b/gi);
  if (words) {
    wordCount.innerHTML = words.length;
  } else {
    wordCount.innerHTML = 0;
  }

  // sentence count	using ./!/? as sentense separators
  if (words) {
    const sentences = input.value.split(/[.|!|?]+/g);
    sentenceCount.innerHTML = sentences.length - 1;
  } else {
    sentenceCount.innerHTML = 0;
  }

  // paragraph count from http://stackoverflow.com/a/3336537
  if (words) {
    // \n$ takes care of empty lines: lines with no characters, and only \n are not paragraphs
    // and need to be replaced with empty string
    const paragraphs = input.value.replace(/\n$/gm, '').split(/\n/);
    paragraphCount.innerHTML = paragraphs.length;
  } else {
    paragraphCount.innerHTML = 0;
  }

  // reading time based on 275 words/minute
  if (words) {
    const seconds = Math.floor((words.length * 60) / 275);
    // need to convert seconds to minutes and hours
    if (seconds > 59) {
      const minutes = Math.floor(seconds / 60);
      const remainingSeconds = seconds - minutes * 60;
      readingTime.innerHTML = minutes + 'm ' + remainingSeconds + 's';
    } else {
      readingTime.innerHTML = seconds + 's';
    }
  } else {
    readingTime.innerHTML = '0s';
  }

  // finding out top keywords and their count
  // step-1: remove all the stop words
  // step-2: form an object with keywords and their count
  // step-3: sort the object by first converting it to a 2D array
  // step-4: display top 4 keywords and their count

  if (words) {
    // step-1: removing all the stop words
    const nonStopWords = [];
    const stopWords = [
      'a',
      'able',
      'about',
      'above',
      'abst',
      'accordance',
      'according',
      'accordingly',
      'across',
      'act',
      'actually',
      'added',
      'adj',
      'affected',
      'affecting',
      'affects',
      'after',
      'afterwards',
      'again',
      'against',
      'ah',
      'all',
      'almost',
      'alone',
      'along',
      'already',
      'also',
      'although',
      'always',
      'am',
      'among',
      'amongst',
      'an',
      'and',
      'announce',
      'another',
      'any',
      'anybody',
      'anyhow',
      'anymore',
      'anyone',
      'anything',
      'anyway',
      'anyways',
      'anywhere',
      'apparently',
      'approximately',
      'are',
      'aren',
      'arent',
      'arise',
      'around',
      'as',
      'aside',
      'ask',
      'asking',
      'at',
      'auth',
      'available',
      'away',
      'awfully',
      'b',
      'back',
      'be',
      'became',
      'because',
      'become',
      'becomes',
      'becoming',
      'been',
      'before',
      'beforehand',
      'begin',
      'beginning',
      'beginnings',
      'begins',
      'behind',
      'being',
      'believe',
      'below',
      'beside',
      'besides',
      'between',
      'beyond',
      'biol',
      'both',
      'brief',
      'briefly',
      'but',
      'by',
      'c',
      'ca',
      'came',
      'can',
      'cannot',
      "can't",
      'cause',
      'causes',
      'certain',
      'certainly',
      'co',
      'com',
      'come',
      'comes',
      'contain',
      'containing',
      'contains',
      'could',
      'couldnt',
      'd',
      'date',
      'did',
      "didn't",
      'different',
      'do',
      'does',
      "doesn't",
      'doing',
      'done',
      "don't",
      'down',
      'downwards',
      'due',
      'during',
      'e',
      'each',
      'ed',
      'edu',
      'effect',
      'eg',
      'eight',
      'eighty',
      'either',
      'else',
      'elsewhere',
      'end',
      'ending',
      'enough',
      'especially',
      'et',
      'et-al',
      'etc',
      'even',
      'ever',
      'every',
      'everybody',
      'everyone',
      'everything',
      'everywhere',
      'ex',
      'except',
      'f',
      'far',
      'few',
      'ff',
      'fifth',
      'first',
      'five',
      'fix',
      'followed',
      'following',
      'follows',
      'for',
      'former',
      'formerly',
      'forth',
      'found',
      'four',
      'from',
      'further',
      'furthermore',
      'g',
      'gave',
      'get',
      'gets',
      'getting',
      'give',
      'given',
      'gives',
      'giving',
      'go',
      'goes',
      'gone',
      'got',
      'gotten',
      'h',
      'had',
      'happens',
      'hardly',
      'has',
      "hasn't",
      'have',
      "haven't",
      'having',
      'he',
      'hed',
      'hence',
      'her',
      'here',
      'hereafter',
      'hereby',
      'herein',
      'heres',
      'hereupon',
      'hers',
      'herself',
      'hes',
      'hi',
      'hid',
      'him',
      'himself',
      'his',
      'hither',
      'home',
      'how',
      'howbeit',
      'however',
      'hundred',
      'i',
      'id',
      'ie',
      'if',
      "i'll",
      'im',
      'immediate',
      'immediately',
      'importance',
      'important',
      'in',
      'inc',
      'indeed',
      'index',
      'information',
      'instead',
      'into',
      'invention',
      'inward',
      'is',
      "isn't",
      'it',
      'itd',
      "it'll",
      'its',
      'itself',
      "i've",
      'j',
      'just',
      'k',
      'keep',
      'keeps',
      'kept',
      'kg',
      'km',
      'know',
      'known',
      'knows',
      'l',
      'largely',
      'last',
      'lately',
      'later',
      'latter',
      'latterly',
      'least',
      'less',
      'lest',
      'let',
      'lets',
      'like',
      'liked',
      'likely',
      'line',
      'little',
      "'ll",
      'look',
      'looking',
      'looks',
      'ltd',
      'm',
      'made',
      'mainly',
      'make',
      'makes',
      'many',
      'may',
      'maybe',
      'me',
      'mean',
      'means',
      'meantime',
      'meanwhile',
      'merely',
      'mg',
      'might',
      'million',
      'miss',
      'ml',
      'more',
      'moreover',
      'most',
      'mostly',
      'mr',
      'mrs',
      'much',
      'mug',
      'must',
      'my',
      'myself',
      'n',
      'na',
      'name',
      'namely',
      'nay',
      'nd',
      'near',
      'nearly',
      'necessarily',
      'necessary',
      'need',
      'needs',
      'neither',
      'never',
      'nevertheless',
      'new',
      'next',
      'nine',
      'ninety',
      'no',
      'nobody',
      'non',
      'none',
      'nonetheless',
      'noone',
      'nor',
      'normally',
      'nos',
      'not',
      'noted',
      'nothing',
      'now',
      'nowhere',
      'o',
      'obtain',
      'obtained',
      'obviously',
      'of',
      'off',
      'often',
      'oh',
      'ok',
      'okay',
      'old',
      'omitted',
      'on',
      'once',
      'one',
      'ones',
      'only',
      'onto',
      'or',
      'ord',
      'other',
      'others',
      'otherwise',
      'ought',
      'our',
      'ours',
      'ourselves',
      'out',
      'outside',
      'over',
      'overall',
      'owing',
      'own',
      'p',
      'page',
      'pages',
      'part',
      'particular',
      'particularly',
      'past',
      'per',
      'perhaps',
      'placed',
      'please',
      'plus',
      'poorly',
      'possible',
      'possibly',
      'potentially',
      'pp',
      'predominantly',
      'present',
      'previously',
      'primarily',
      'probably',
      'promptly',
      'proud',
      'provides',
      'put',
      'q',
      'que',
      'quickly',
      'quite',
      'qv',
      'r',
      'ran',
      'rather',
      'rd',
      're',
      'readily',
      'really',
      'recent',
      'recently',
      'ref',
      'refs',
      'regarding',
      'regardless',
      'regards',
      'related',
      'relatively',
      'research',
      'respectively',
      'resulted',
      'resulting',
      'results',
      'right',
      'run',
      's',
      'said',
      'same',
      'saw',
      'say',
      'saying',
      'says',
      'sec',
      'section',
      'see',
      'seeing',
      'seem',
      'seemed',
      'seeming',
      'seems',
      'seen',
      'self',
      'selves',
      'sent',
      'seven',
      'several',
      'shall',
      'she',
      'shed',
      "she'll",
      'shes',
      'should',
      "shouldn't",
      'show',
      'showed',
      'shown',
      'showns',
      'shows',
      'significant',
      'significantly',
      'similar',
      'similarly',
      'since',
      'six',
      'slightly',
      'so',
      'some',
      'somebody',
      'somehow',
      'someone',
      'somethan',
      'something',
      'sometime',
      'sometimes',
      'somewhat',
      'somewhere',
      'soon',
      'sorry',
      'specifically',
      'specified',
      'specify',
      'specifying',
      'still',
      'stop',
      'strongly',
      'sub',
      'substantially',
      'successfully',
      'such',
      'sufficiently',
      'suggest',
      'sup',
      'sure',
      't',
      'take',
      'taken',
      'taking',
      'tell',
      'tends',
      'th',
      'than',
      'thank',
      'thanks',
      'thanx',
      'that',
      "that'll",
      'thats',
      "that've",
      'the',
      'their',
      'theirs',
      'them',
      'themselves',
      'then',
      'thence',
      'there',
      'thereafter',
      'thereby',
      'thered',
      'therefore',
      'therein',
      "there'll",
      'thereof',
      'therere',
      'theres',
      'thereto',
      'thereupon',
      "there've",
      'these',
      'they',
      'theyd',
      "they'll",
      'theyre',
      "they've",
      'think',
      'this',
      'those',
      'thou',
      'though',
      'thoughh',
      'thousand',
      'throug',
      'through',
      'throughout',
      'thru',
      'thus',
      'til',
      'tip',
      'to',
      'together',
      'too',
      'took',
      'toward',
      'towards',
      'tried',
      'tries',
      'truly',
      'try',
      'trying',
      'ts',
      'twice',
      'two',
      'u',
      'un',
      'under',
      'unfortunately',
      'unless',
      'unlike',
      'unlikely',
      'until',
      'unto',
      'up',
      'upon',
      'ups',
      'us',
      'use',
      'used',
      'useful',
      'usefully',
      'usefulness',
      'uses',
      'using',
      'usually',
      'v',
      'value',
      'various',
      "'ve",
      'very',
      'via',
      'viz',
      'vol',
      'vols',
      'vs',
      'w',
      'want',
      'wants',
      'was',
      "wasn't",
      'way',
      'we',
      'wed',
      'welcome',
      "we'll",
      'went',
      'were',
      "weren't",
      "we've",
      'what',
      'whatever',
      "what'll",
      'whats',
      'when',
      'whence',
      'whenever',
      'where',
      'whereafter',
      'whereas',
      'whereby',
      'wherein',
      'wheres',
      'whereupon',
      'wherever',
      'whether',
      'which',
      'while',
      'whim',
      'whither',
      'who',
      'whod',
      'whoever',
      'whole',
      "who'll",
      'whom',
      'whomever',
      'whos',
      'whose',
      'why',
      'widely',
      'willing',
      'wish',
      'with',
      'within',
      'without',
      "won't",
      'words',
      'world',
      'would',
      "wouldn't",
      'www',
      'x',
      'y',
      'yes',
      'yet',
      'you',
      'youd',
      "you'll",
      'your',
      'youre',
      'yours',
      'yourself',
      'yourselves',
      "you've",
      'z',
      'zero',
    ];
    for (var i = 0; i < words.length; i++) {
      // filtering out stop words and numbers
      if (stopWords.indexOf(words[i].toLowerCase()) === -1 && isNaN(words[i])) {
        nonStopWords.push(words[i].toLowerCase());
      }
    }
    // console.log(nonStopWords);

    // step-2: forming an object with keywords and their count
    var keywords = {};
    for (var i = 0; i < nonStopWords.length; i++) {
      // checking if the word(property) already exists
      // if it does increment the count otherwise set it to one
      if (nonStopWords[i] in keywords) {
        keywords[nonStopWords[i]] += 1;
      } else {
        keywords[nonStopWords[i]] = 1;
      }
    }

    // step-3: sorting the object by first converting it to a 2D array
    var sortedKeywords = [];
    for (var keyword in keywords) {
      sortedKeywords.push([keyword, keywords[keyword]]);
    }
    sortedKeywords.sort(function (a, b) {
      return b[1] - a[1];
    });
    // console.log(sortedKeywords);

    // step-4: displaying top 4 keywords and their count
    topKeywords.innerHTML = '';
    for (var i = 0; i < sortedKeywords.length && i < 4; i++) {
      var li = document.createElement('li');
      li.innerHTML = '<b>' + sortedKeywords[i][0] + '</b>: ' + sortedKeywords[i][1];
      topKeywords.appendChild(li);
    }
  }

  // displaying top keywords only if there is a word in the text area
  if (words) {
    keywordsDiv.style.display = 'block';
  } else {
    keywordsDiv.style.display = 'none';
  }
});
